Lambda 関数の実行ログが出力されるログストリーム名を Lambda コンテキストから取得する
コンバンハ、千葉(幸)です。
Lambda 関数の実行ログは/aws/lambda/<Lambda関数名>
という CloudWatch Logs ロググループに出力されます。
ロググループ内でログストリームが動的に生成され、その中に出力されていきます。ログストリーム名は以下の命名規則になっています。
YYYY/MM/DD/[<Lambda関数 のバージョン>]<ランダムな識別子>
以下のイメージです。
このログストリーム名を動的に取得したい、ということで Lambda コンテキストを使用してみました。
やりたいこと
以下のスクリプトのように Lambda 関数の実行とログ取得を行いたいです。
#!/bin/bash aws lambda invoke --function-name my-function --cli-binary-format raw-in-base64-out --payload '{"key": "value"}' out sed -i'' -e 's/"//g' out sleep 15 aws logs get-log-events --log-group-name /aws/lambda/my-function --log-stream-name $(cat out) --limit 5
ここでは Lambda 関数の返り値としてログストリーム名が返ってくることが前提になっています。そのために Lambda コンテキストを使用します。
Lambda 関数の作成
今回は設計図hello-world-python
を用いて Lambda 関数を作成しました。
- 関数名:hello-world-python
- ランタイム:Python 3.7
- IAM ロール:自動作成に任せる
コードの中身は以下です。
import json print('Loading function') def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=2)) print("value1 = " + event['key1']) print("value2 = " + event['key2']) print("value3 = " + event['key3']) return event['key1'] # Echo back the first key value #raise Exception('Something went wrong')
渡されたイベントの key1 の値を返すようになっています。
Lambda 関数の実行
上記の状態で AWS CLI から Lambda 関数を実行してみます。
まず環境変数を格納。
FUNCTION_NAME=hello-world-python PAYLOAD=$(cat <<EOM { "key1": "value1", "key2": "value2", "key3": "value3" } EOM )
上記を引数に使用して実行します。
$ aws lambda invoke --function-name $FUNCTION_NAME --cli-binary-format raw-in-base64-out --payload "$PAYLOAD" out { "StatusCode": 200, "ExecutedVersion": "$LATEST" }
--cli-binary-format raw-in-base64-out
を指定しないとペイロードが base64 エンコードされたテキストとして扱われるため、それを回避するために指定します。
outfile として指定したout
にはreturn event['key1']
の内容が格納されています。
$ cat out "value1"
Lambda コンテキストの使用
コードの内容を以下に書き換えます。return で返す内容をcontext.log_stream_name
に変更しています。
import json print('Loading function') def lambda_handler(event, context): print("Received event: " + json.dumps(event, indent=2)) print("value1 = " + event['key1']) print("value2 = " + event['key2']) print("value3 = " + event['key3']) # return event['key1'] # Echo back the first key value return context.log_stream_name #raise Exception('Something went wrong')
ここではlog_stream_name
を指定しましたが、他にも利用できる Lambda コンテキストオブジェクトがあります。
Lambda コンテキストによるログストリーム名の取得
コードを修正した状態で再度 Lambda 関数を実行します。
$ aws lambda invoke --function-name $FUNCTION_NAME --cli-binary-format raw-in-base64-out --payload "$PAYLOAD" out { "StatusCode": 200, "ExecutedVersion": "$LATEST" } $ cat out "2022/03/21/[$LATEST]7d0c88909f86424bbe40b4c0cfcdb08f"
ログストリーム名が返り値として取得できていることが分かります。
冒頭のスクリプトと同等のコマンドを実行します。2 行目の sed の処理は"
を除去するためのものです。
aws lambda invoke --function-name $FUNCTION_NAME --cli-binary-format raw-in-base64-out --payload "$PAYLOAD" out sed -i'' -e 's/"//g' out sleep 15 aws logs get-log-events --log-group-name /aws/lambda/$FUNCTION_NAME --log-stream-name $(cat out) --limit 5
実行するときちんとログストリーム内のログイベントが取得できました。
$ aws lambda invoke --function-name $FUNCTION_NAME --cli-binary-format raw-in-base64-out --payload "$PAYLOAD" out sed -i'' -e 's/"//g' out sleep 15 aws logs get-log-events --log-group-name /aws/lambda/$FUNCTION_NAME --log-stream-name $(cat out) --limit 5 { "StatusCode": 200, "ExecutedVersion": "$LATEST" } { "events": [ { "timestamp": 1647838819665, "message": "value1 = value1\n", "ingestionTime": 1647838828689 }, { "timestamp": 1647838819665, "message": "value2 = value2\n", "ingestionTime": 1647838828689 }, { "timestamp": 1647838819665, "message": "value3 = value3\n", "ingestionTime": 1647838828689 }, { "timestamp": 1647838819666, "message": "END RequestId: 37e94215-8d36-4ea8-a5cd-b850f20217a5\n", "ingestionTime": 1647838828689 }, { "timestamp": 1647838819666, "message": "REPORT RequestId: 37e94215-8d36-4ea8-a5cd-b850f20217a5\tDuration: 1.51 ms\tBilled Duration: 2 ms\tMemory Size: 128 MB\tMax Memory Used: 36 MB\t\n", "ingestionTime": 1647838828689 } ], "nextForwardToken": "f/36748033645618918877095797763546468513774900547129573386/s", "nextBackwardToken": "b/36748033645596618131897267140404932795502252185623592966/s" }
ちなみに
Lambda コンソールから実行した場合は以下のように見えます。
「テスト」タブから実行した場合。
「コード」タブから実行した場合。
終わりに
Lambda コンテキストによりログ出力先のログストリーム名を取得してみました。今回は Python の例を試したましたが、他の言語のランタイムでも同様のことが実現できます。
こういったこともできる、と覚えておくとどこかで役に立つかもしれません。
以上、 チバユキ (@batchicchi) がお送りしました。